import numpy as np
from pymoo.algorithms.soo.nonconvex.ga import GA
from pymoo.algorithms.soo.nonconvex.de import DE
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.core.problem import Problem
from pymoo.operators.crossover.pntx import TwoPointCrossover  # GA专用交叉算子
from pymoo.operators.mutation.pm import PolynomialMutation    # GA专用变异算子
from pymoo.operators.selection.tournament import TournamentSelection  # 选择算子
from pymoo.optimize import minimize
import pandas as pd
import time

# ====================== 基础参数设置 ======================
T = 144  # 3天×24小时×2时段/小时
dt = 0.5 * 3600  # 时段长度（秒）

def storage_sg_func(v_array):
    """
    向量化计算存储函数值（支持ndarray输入）

    参数:
    v_array (ndarray): 待计算的容积数组（单位：万m³）

    返回:
    ndarray: 计算结果数组（超出区间的值为np.nan）
    """
    # 转换为浮点数组避免整数运算问题
    v = v_array.astype(np.float64)

    # 定义区间条件
    cond1 = np.logical_and(v > -np.inf, v <= 2.58)  # 区间 [0, 2.58]
    cond2 = np.logical_and(v > 2.58, v <= np.inf)  # 区间 (2.58, 311.02]

    # 计算各区间的多项式值
    poly1 = -0.4068 * (v ** 3) + 0.3595 * (v ** 2) + 0.5759 * v + 4.5012
    poly2 = 2e-07 * (v ** 3) - 0.0001 * (v ** 2) + 0.0472 * v + 5.1436

    # 根据条件选择结果（超出区间返回np.nan）
    result = np.select([cond1, cond2], [poly1, poly2], default=np.nan)

    return result


def storage_sg_inv_func(h_array):
    """
    向量化计算水位-库容反函数值（支持ndarray输入）

    参数:
    h_array (ndarray): 待计算的水位数组（单位：m）

    返回:
    ndarray: 计算结果数组（超出区间的值为np.nan）
    """
    # 转换为浮点数组避免整数运算问题
    h = h_array.astype(np.float64)

    # 定义区间条件
    cond1 = np.logical_and(h >= 4.5, h <= 5.11)  # 区间 [4.5, 5.11]
    cond2 = np.logical_and(h > 5.11, h <= 13)  # 区间 (5.11, 13]

    # 计算各区间的多项式值
    poly1 = 4.0878 * (h ** 3) - 57.49 * (h ** 2) + 270.92 * h - 427.45
    poly2 = -0.3646 * (h ** 3) + 12.367 * (h ** 2) - 89.848 * h + 190.18

    # 根据条件选择结果（超出区间返回np.nan）
    result = np.select([cond1, cond2], [poly1, poly2], default=np.nan)

    return result


# 水库参数（保持不变）
reservoir_params = {
    'A': {
        'storage_func': lambda V: -0.0000004 * V ** 2 + 0.0052 * V + 14.783,  # 库容-水位函数 V(万m³)->Z(m)
        'storage_inv_func': lambda H: 13.767 * H ** 2 - 362.59 * H + 2868.2,  # 水位-库容反函数 Z(m)->V(万m³)
        'Q_min': 0,  # 最小出库流量(m³/s)
        'Q_max': 270,  # 最大出库流量(m³/s)
        'H_initial': 26.6,
        'V_initial': 3348.4  # 初始库容(万m³) 深圳水库
    },
    'B': {
        'storage_func': 0,
        'storage_inv_func': 0,
        'Q_min': 0,
        'Q_max': 690,
        'H_initial': 11.73,
        'V_initial': 240.61  # 笋岗滞洪区
    }
}
# 断面参数
section_params = {
    'gate_SCHK': {
        'H_initial': 2.5,
        'Q_to_H_func': lambda Q: 0.1568 * (Q ** 0.5494)  # 幂函数：H = a*Q^b，其中a=0.1568，b=0.5494 断面流量-水位关系
    },
    'gate_WJD': {
        'H_initial': 2.5,
        'Q_to_H_func': lambda Q: 0.1361 * (Q ** 0.5685)  #  断面流量-水位关系
    },
    'gate_LHZ': {
        'H_initial': 2.5,
        'Q_to_H_func': lambda Q: 0.0907 * (Q ** 0.6065)  # 幂函数：H = a*Q^b，其中a=0.1568，b=0.5494 断面流量-水位关系
    },
    'gate_BJHK': {
        'H_initial': 2.5,
        'Q_to_H_func': lambda Q: 0.3943 * (Q ** 0.3917)
    },
    'gate_LDC': {
        'H_initial': 2.5,
        'Q_to_H_func': lambda Q: 0.0675 * (Q ** 0.5805)
    },
    'gate_SBMT': {
        'H_initial': 2.5,
        'Q_to_H_func': lambda Q: 0.0505 * (Q ** 0.6086)
    },
    'gate_SZHK': {
        'H_initial': 2.5,
        'Q_to_H_func': lambda Q: 0.0011 * Q + 0.7779
    }

}
# 水闸流达时间（分钟）→ 转换为时段数（半小时为一时段）
travel_time = {
    'A到三岔河口': 6,  # A水库到三岔河口
    '三岔河口到文锦渡': 8.1,  # 三岔河口到文锦渡
    '文锦渡到罗湖站': 25,  # 文锦渡到罗湖站
    '罗湖站到布吉河口': 13,  # 罗湖站到布吉河口
    'B到布吉河口': 12,  # B水库到布吉河口
    '布吉河口、罗湖站到鹿丹村': 38,  # 布吉河口到鹿丹村
    '鹿丹村到上步码头': 10,  # 鹿丹村到上步码头
    '上步码头到深圳河口': 6  # 上步码头到深圳河口
}
# 转换为时段数（向上取整）
travel_time_period = {k: int(np.ceil(v / 30)) for k, v in travel_time.items()}


# 水闸列表（按下游顺序）
# downstream_gates = ['布吉河口', '鹿丹村', '上步码头', '深圳河口']
def load_inflow_data(excel_path):
    try:
        # 从Excel读取数据，假设Excel文件包含'A_inflow'和'B_inflow'两列
        df = pd.read_excel(excel_path)

        # 检查数据行数是否为时段数
        if len(df) != T:
            raise ValueError(f"数据行数应为{T}行，当前读取到{len(df)}行")

        # 检查是否包含所需列
        required_columns = ['Date Time','笋岗滞洪区入流', '深圳水库入流']
        if not set(required_columns).issubset(df.columns):
            missing = [col for col in required_columns if col not in df.columns]
            raise KeyError(f"Excel文件缺少必要列: {missing}")

        return df[required_columns]

    except FileNotFoundError:
        print(f"错误：未找到文件 {excel_path}")
        return None
    except Exception as e:
        print(f"读取数据时发生错误: {str(e)}")
        return None


# 200年一遇洪水过程 3天
excel_file = "inflow_data_200a.xlsx"
inflow_data = load_inflow_data(excel_file)
A_lateral_inflow = np.zeros(T)  # 深圳水库旁侧入流（来水）
B_lateral_inflow = np.zeros(T)  # 笋岗滞洪区旁侧入流（来水）
if inflow_data is not None:
    print("成功读取入库流量数据：")
    print(inflow_data.head())  # 打印前5行验证


def compute_flow(upstream_flow, delay, total_time):
    """
    通用流量计算函数
    :param upstream_flow: 上游流量数组
    :param delay: 延迟时段
    :param total_time: 总时间步长T
    :return: 当前节点流量数组
    """
    return np.array([
        upstream_flow[t - delay] if t >= delay else 0
        for t in range(total_time)
    ])


# ====================== 模型 ======================
class ReservoirOptimizationProblem(Problem):
    def __init__(self):
        super().__init__(
            n_var=2 * T,  # 决策变量：A水库T时段出库 + B水库T时段出库
            n_obj=1,  # 单目标优化
            n_constr=10 * T,  # 约束
            xl=np.array([reservoir_params['A']['Q_min']] * T + [reservoir_params['B']['Q_min']] * T),  # 出库下限
            xu=np.array([reservoir_params['A']['Q_max']] * T + [reservoir_params['B']['Q_max']] * T)  # 出库上限
        )
        self.flow_processes = []  # 保存水库、断面的流量过程

    def _evaluate(self, X, out, *args, **kwargs):
        f = []  # 目标函数值（洪峰流量）
        g = []  # 约束条件

        for x in X:
            # 分解决策变量
            Q_A = x[:T]  # 深圳水库A各时段出库流量(m³/s)
            Q_B = x[T:]  # 笋岗滞洪区B各时段出库流量(m³/s)

            # ---------------------- 水库调蓄计算 ----------------------
            # 深圳水库A水量平衡
            V_A = np.zeros(T + 1)  # 库容序列 万m³
            H_A = np.zeros(T + 1)  # 深圳水库水位 m
            V_A[0] = reservoir_params['A']['V_initial']  # 深圳水库初始流量
            H_A[0] = reservoir_params['A']['H_initial']  # 深圳水库初始水位

            # 笋岗滞洪区B水量平衡
            V_B = np.zeros(T + 1)  # 笋岗滞洪区库容序列（万m³）
            H_B = np.zeros(T + 1)  # 笋岗滞洪区水位 m
            V_B[0] = reservoir_params['B']['V_initial']  # 笋岗滞洪区初始水位
            H_B[0] = reservoir_params['B']['H_initial']  # 笋岗滞洪区初始水位
            for t in range(T):
                inflow = inflow_data['深圳水库入流'].iloc[t]  # 深圳水库入库流量(m³/s)
                inflow1 = inflow_data['笋岗滞洪区入流'].iloc[t]  # 笋岗滞洪区入库流量(m³/s)
                V_A[t + 1] = V_A[t] + (inflow - Q_A[t]) * dt / 10000  # 转换为万m³
                H_A[t + 1] = reservoir_params['A']['storage_func'](V_A[t + 1])

                # if V_B[t] < 311:
                #     Q_B[t] = 0
                #     V_B[t + 1] = V_B[t] + (inflow1 - Q_B[t]) * dt / 10000
                #     H_B[t + 1] = storage_sg_func(V_B[t + 1])
                # else:
                V_B[t + 1] = V_B[t] + (inflow1 - Q_B[t]) * dt / 10000
                H_B[t + 1] = storage_sg_func(V_B[t + 1])

            # ---------------------- 下游水闸流量计算 ----------------------
            # 1. 计算布罗湖站流量（A和B的汇流）
            # A到罗湖站的延迟时段路径：A→三岔河口→文锦渡→罗湖站
            delay_dict = {
                'A到罗湖站': (travel_time_period['A到三岔河口'] +
                              travel_time_period['三岔河口到文锦渡'] +
                              travel_time_period['文锦渡到罗湖站']),
                'B到布吉河口': travel_time_period['B到布吉河口'],
                '布吉罗湖到鹿丹村': travel_time_period['布吉河口、罗湖站到鹿丹村'],
                '鹿丹村到上步码头': travel_time_period['鹿丹村到上步码头'],
                '上步到深圳河口': travel_time_period['上步码头到深圳河口']
            }

            # 1. 计算罗湖站流量（深圳水库→罗湖）
            Q_LHZ = compute_flow(Q_A, delay_dict['A到罗湖站'], T)
            # 罗湖水位
            H_LHZ = np.zeros(T)
            for t in range(T):
                if t == 0:
                    H_LHZ[t] = section_params['gate_LHZ']['H_initial']
                elif Q_LHZ[t] == 0:
                    H_LHZ[t] = H_LHZ[t - 1]
                else:
                    H_LHZ[t] = section_params['gate_LHZ']['Q_to_H_func'](Q_LHZ[t])
            # 2.笋岗滞洪区到布吉河口的流量
            Q_BJHK = compute_flow(Q_B, delay_dict['B到布吉河口'], T)
            # TODO:布吉河水位
            H_BJHK = np.zeros(T)
            for t in range(T):
                if t == 0:
                    H_BJHK[t] = section_params['gate_BJHK']['H_initial']
                elif Q_BJHK[t] == 0:
                    H_BJHK[t] = H_BJHK[t - 1]
                else:
                    H_BJHK[t] = section_params['gate_BJHK']['Q_to_H_func'](Q_BJHK[t])
            # 3.计算鹿丹村流量（布吉河口+ B→布吉河口 共同延迟到鹿丹村）
            Q_LDC = compute_flow(Q_LHZ + Q_BJHK, delay_dict['布吉罗湖到鹿丹村'], T)
            # TODO:鹿丹村水位
            # 4.计算上步码头流量（鹿丹村→上步码头）
            Q_SBMT = compute_flow(Q_LDC, delay_dict['鹿丹村到上步码头'], T)
            # TODO:上步码头水位
            # 5. 计算深圳河口流量（上步码头→深圳河口）
            Q_SZHK = compute_flow(Q_SBMT, delay_dict['上步到深圳河口'], T)
            # TODO:深圳河口水位

            # ---------------------- 目标函数：下游最大洪峰流量 ----------------------
            # 各水闸的洪峰流量（过程最大值）

            peak_LHZ = np.max(Q_LHZ)
            peak_BJHK = np.max(Q_BJHK)
            peak_LDC = np.max(Q_LDC)
            peak_SBMT = np.max(Q_SBMT)
            peak_SZHK = np.max(Q_SZHK)

            # 下游整体最大洪峰（取所有水闸的最大值）
            total_peak_q = np.max([peak_LHZ, peak_BJHK, peak_LDC, peak_SBMT, peak_SZHK])
            total_peak_h = np.max([H_LHZ]) + np.max([H_BJHK])

            # total_v = 0
            # for t in range(T):
            #     total_v += (V_B[t+1] - V_B[t]) ** 2

            # 水位波动最小
            total_h = 0
            # 出库流量最小
            total_q = 0
            # 断面流量超过阈值次数
            num_bjhk = 0
            num_ljz = 0
            for t in range(T):
                total_h += (
                        (H_LHZ[t] - section_params['gate_LHZ']['H_initial']) ** 2
                        + (H_BJHK[t] - section_params['gate_BJHK']['H_initial']) ** 2
                )
                total_q += Q_A[t] + Q_B[t]
            # if Q_BJHK[t] > Q_BJHK[max] 如果超过最大流量，次数加一，但是最大流量未知

            # 整体流量波动最小
            fluctuation_Q = 0
            for t in range(T - 1):
                fluctuation_Q += Q_A[t + 1] - Q_A[t] + Q_B[t + 1] - Q_B[t]

            total_v = 0
            for t in range(T):
                total_v += (
                        (V_A[t + 1] - reservoir_params['A']['V_initial']) ** 2
                        + (V_B[t + 1] - reservoir_params['B']['V_initial']) ** 2
                )

            total_b_v = 0
            for t in range(T):
                total_b_v += V_B[t + 1]
            f.append(fluctuation_Q)

            # ---------------------- 约束条件 ----------------------
            # 1. 深圳水库时段末库容非负（V(t+1) ≥ 0）
            constr_vA = -V_A[1:]  # -V ≤ 0 → V ≥ 0

            # 2. 笋岗滞洪区时段末库容非负
            constr_vB = -V_B[1:]
            constr_vB1 = 311 - V_B[1:]
            # 3. 深圳水库水位不超设计上限
            Z_A = reservoir_params['A']['storage_func'](V_A[1:])  # 时段初水位
            constr_zA = Z_A - 28.83  # Z - Z_max ≤ 0

            constr_zA1 = 24.3 - Z_A
            # 4. 笋岗滞洪区水位不超设计上限
            constr_zB = H_B[1:] - 13
            # 5. 笋岗滞洪区水位不超设计下限
            constr_zB1 = 6 - H_B[1:]

            # 6. 罗湖站断面水位不超设计上限
            constr_h_LHZ = H_LHZ - 5.816  #上限 5.816
            constr_h_LHZ1 = 0 - H_LHZ  #下限0
            
            # 7. 布吉河口断面水位不超设计上限
            constr_h_BJHK = H_BJHK - 5.15  # 上限 5.15
            constr_h_BJHK1 = 0 - H_BJHK  # 下限0
            # 合并所有约束（g ≤ 0 表示可行）
            g.append(np.concatenate([constr_vA,
                                     constr_vB,
                                     # constr_vB1,
                                     constr_zA,
                                     constr_zA1,
                                     constr_zB,
                                     constr_zB1,
                                     constr_h_LHZ,
                                     constr_h_LHZ1,
                                     constr_h_BJHK,
                                     constr_h_BJHK1
                                     ])
                     )
            # 保存当前解的流量过程
            self.flow_processes.append({
                '深圳水库出库流量': Q_A,
                '笋岗滞洪区出库流量': Q_B,
                '深圳水库水位': H_A[1:],
                '深圳水库库容': V_A[1:],
                '笋岗滞洪区水位': H_B[1:],
                '笋岗滞洪区库容': V_B[1:],
                '罗湖站流量': Q_LHZ,
                '罗湖站水位': H_LHZ,
                '布吉河口流量': Q_BJHK,
                '布吉河口水位': H_BJHK,
            })
        out["F"] = np.array(f).reshape(-1, 1)  # 目标函数值
        out["G"] = np.array(g)  # 约束条件


# ====================== 打印优化过程 ======================
def optimization_callback(algorithm):
    """回调函数：输出每代优化进度"""
    gen = algorithm.n_gen
    current_fitness = np.min(algorithm.pop.get("F"))
    print(f"第 {gen:3d} 代 | 当前适应度: {current_fitness:.2f} m³")


if __name__ == "__main__":
    start_time = time.perf_counter()  # 记录开始时间（高精度计时器）
    # 初始化优化问题
    problem = ReservoirOptimizationProblem()

    # 配置差分进化算法
    # algorithm = GA(
    #     pop_size=100,  # 增大种群大小（原50→100）提升多样性搜索能力
    #     selection=TournamentSelection(func_comp=lambda a, b: a.get("F") < b.get("F")),  # 锦标赛选择
    #     crossover=TwoPointCrossover(prob=0.8),  # 两点交叉（概率0.8）
    #     mutation=PolynomialMutation(prob=0.1, eta=20),  # 多项式变异（概率0.1，eta控制变异步长）
    #     eliminate_duplicates=True,  # 消除重复个体提升效率
    #     callback_data=[],  # 用于存储回调数据的列表
    # )
    algorithm = DE(
        pop_size=50,  # 种群大小
        variant="DE/rand/1/bin",  # 算法变体
        CR=0.7,  # 交叉概率
        F=0.5,  # 缩放因子
        dither="vector",  # 增加扰动提高多样性
        jitter=False
    )

    # 运行优化
    res = minimize(
        problem,
        algorithm,
        termination=('n_gen', 1000),  # 迭代次数
        callback=optimization_callback,  # 显示优化过程
        seed=123,  # 随机种子
        verbose=False  # 关闭默认输出
    )

    print(f"最终种群目标值: {res.F}")
    # 输出结果
    # print(f"\n优化完成,最终最小水位违反值: {res.F[0]:.2f} m")

    # 保存最优出库方案
    optimal_Q_A = res.X[:T]  # 深圳水库A最优出库序列
    optimal_Q_B = res.X[T:]  # 笋岗滞洪区B最优出库序列

    # ---------------------- 水库调蓄计算 ----------------------
    # 深圳水库A水量平衡
    V_A = np.zeros(T + 1)  # 库容序列 万m³
    H_A = np.zeros(T + 1)  # 深圳水库水位 m
    V_A[0] = reservoir_params['A']['V_initial']  # 深圳水库初始流量
    H_A[0] = reservoir_params['A']['H_initial']  # 深圳水库初始水位

    # 笋岗滞洪区B水量平衡
    V_B = np.zeros(T + 1)  # 笋岗滞洪区库容序列（万m³）
    H_B = np.zeros(T + 1)  # 笋岗滞洪区水位 m
    V_B[0] = reservoir_params['B']['V_initial']  # 笋岗滞洪区初始水位
    H_B[0] = reservoir_params['B']['H_initial']  # 笋岗滞洪区初始水位
    for t in range(T):
        inflow = inflow_data['深圳水库入流'].iloc[t]  # 深圳水库入库流量(m³/s)
        inflow1 = inflow_data['笋岗滞洪区入流'].iloc[t]  # 笋岗滞洪区入库流量(m³/s)
        V_A[t + 1] = V_A[t] + (inflow - optimal_Q_A[t]) * dt / 10000  # 转换为万m³
        H_A[t + 1] = reservoir_params['A']['storage_func'](V_A[t + 1])

        # if V_B[t] < 300:
        #     Q_B[t] = 0
        #     V_B[t + 1] = V_B[t] + (inflow1 - Q_B[t]) * dt / 10000
        #     H_B[t + 1] = storage_sg_func(V_B[t + 1])
        # if inflow1 > Q_B[t] and inflow1 >300 :
        #     Q_B[t] = inflow1
        V_B[t + 1] = V_B[t] + (inflow1 - optimal_Q_B[t]) * dt / 10000
        H_B[t + 1] = storage_sg_func(V_B[t + 1])

    # ---------------------- 下游水闸流量计算 ----------------------
    # 1. 计算布罗湖站流量（A和B的汇流）
    # A到罗湖站的延迟时段路径：A→三岔河口→文锦渡→罗湖站
    delay_dict = {
        'A到罗湖站': (travel_time_period['A到三岔河口'] +
                      travel_time_period['三岔河口到文锦渡'] +
                      travel_time_period['文锦渡到罗湖站']),
        'B到布吉河口': travel_time_period['B到布吉河口'],
        '布吉罗湖到鹿丹村': travel_time_period['布吉河口、罗湖站到鹿丹村'],
        '鹿丹村到上步码头': travel_time_period['鹿丹村到上步码头'],
        '上步到深圳河口': travel_time_period['上步码头到深圳河口']
    }

    # 1. 计算罗湖站流量（深圳水库→罗湖）
    Q_LHZ = compute_flow(optimal_Q_A, delay_dict['A到罗湖站'], T)
    # 罗湖水位
    H_LHZ = np.zeros(T)
    for t in range(T):
        if t == 0:
            H_LHZ[t] = section_params['gate_LHZ']['H_initial']
        elif Q_LHZ[t] == 0:
            H_LHZ[t] = H_LHZ[t - 1]
        else:
            H_LHZ[t] = section_params['gate_LHZ']['Q_to_H_func'](Q_LHZ[t])
    # 2.笋岗滞洪区到布吉河口的流量
    Q_BJHK = compute_flow(optimal_Q_B, delay_dict['B到布吉河口'], T)
    # TODO:布吉河水位
    H_BJHK = np.zeros(T)
    for t in range(T):
        if t == 0:
            H_BJHK[t] = section_params['gate_BJHK']['H_initial']
        elif Q_BJHK[t] == 0:
            H_BJHK[t] = H_BJHK[t - 1]
        else:
            H_BJHK[t] = section_params['gate_BJHK']['Q_to_H_func'](Q_BJHK[t])
    # 3.计算鹿丹村流量（布吉河口+ B→布吉河口 共同延迟到鹿丹村）
    Q_LDC = compute_flow(Q_LHZ + Q_BJHK, delay_dict['布吉罗湖到鹿丹村'], T)
    # TODO:鹿丹村水位
    # 4.计算上步码头流量（鹿丹村→上步码头）
    Q_SBMT = compute_flow(Q_LDC, delay_dict['鹿丹村到上步码头'], T)
    # TODO:上步码头水位
    # 5. 计算深圳河口流量（上步码头→深圳河口）
    Q_SZHK = compute_flow(Q_SBMT, delay_dict['上步到深圳河口'], T)
    # TODO:深圳河口水位

    # ---------------------- 目标函数：下游最大洪峰流量 ----------------------

    # 水位波动最小
    total_h = 0
    for t in range(T):
        total_h += (
                    (H_LHZ[t] - section_params['gate_LHZ']['H_initial']) ** 2
                    + (H_BJHK[t] - section_params['gate_BJHK']['H_initial']) ** 2
                    )

    total_v = 0
    for t in range(T):
        total_v += (
                (V_A[t + 1] - reservoir_params['A']['V_initial']) ** 2
                + (V_B[t + 1] - reservoir_params['B']['V_initial']) ** 2
        )

    # 提取最优解的索引
    optimal_index = np.argmin(res.F)

    # 从保存的流量过程中提取最优解的流量过程
    optimal_flow_process = problem.flow_processes[optimal_index]

    # 创建包含所有水闸流量的DataFrame
    flow_process_df = (pd.DataFrame({
        '时段': inflow_data['Date Time'],
        '深圳水库出库流量(m³/s)': optimal_Q_A,
        '笋岗滞洪区出库流量(m³/s)': optimal_Q_B,
        '': '',
        '深圳水库水位(m)': H_A[1:],
        '深圳水库库容(万m³)': V_A[1:],
        '笋岗滞洪区水位(m)': H_B[1:],
        '笋岗滞洪区库容(万m³)': V_B[1:],
        ' ': '',
        '罗湖站流量(m³/s)': Q_LHZ,
        '罗湖站水位(m)': H_LHZ,
        '布吉河口流量(m³/s)': Q_BJHK,
        '布吉河口水位(m)': H_BJHK,

    }))

    excel_name = '流量水位过程_200A_出库波动最小.xlsx'
    flow_process_df.to_excel(excel_name, index=False)

    # 输出提示信息
    print("\n调度过程已保存至" + excel_name + '。')

    end_time = time.perf_counter()  # 记录结束时间
    execution_time = end_time - start_time
    print(f"程序运行时间：{execution_time:.6f} 秒")

